package com.sun.dream.fish.secret.asymmetry;

import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.ElGamalEngine;
import org.bouncycastle.crypto.generators.ElGamalKeyPairGenerator;
import org.bouncycastle.crypto.params.ElGamalKeyGenerationParameters;
import org.bouncycastle.crypto.params.ElGamalParameters;
import org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters;
import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.*;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;

public class ElGamalExample {
    public static void main(String[] args) throws InvalidCipherTextException, NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException {
        Security.addProvider(new BouncyCastleProvider());

        // 生成密钥对
        AsymmetricCipherKeyPair keyPair = generateKeyPair();
        ElGamalPublicKeyParameters publicKey = (ElGamalPublicKeyParameters) keyPair.getPublic();
        ElGamalPrivateKeyParameters privateKey = (ElGamalPrivateKeyParameters) keyPair.getPrivate();

        // 要加密的原始数据
        byte[] plainText = "Hello, world!".getBytes();
        // 生成对称密钥
        //注释为可以配合对称加密AES实现对称密钥加密
//        SecretKey aesKey = generateAesKey();
        // 使用对称密钥加密数据
//        Cipher aesCipher = Cipher.getInstance("AES");
//        aesCipher.init(Cipher.ENCRYPT_MODE, aesKey);
//
//        byte[] encryptedData = aesCipher.doFinal(plainText);

        // 使用ElGamal公钥加密对称密钥
        ElGamalEngine elGamalEngine = new ElGamalEngine();
        elGamalEngine.init(true, publicKey);
        byte[] encryptedKey = elGamalEngine.processBlock(plainText, 0, plainText.length);

        // 使用ElGamal私钥解密对称密钥
        elGamalEngine.init(false, privateKey);
        byte[] decryptedKey = elGamalEngine.processBlock(encryptedKey, 0, encryptedKey.length);

        // 使用解密后的对称密钥解密数据
//        Cipher aesDecryptCipher = Cipher.getInstance("AES");
//        aesDecryptCipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptedKey, "AES"));
//        byte[] decryptedData = aesDecryptCipher.doFinal(encryptedData);

        // 打印加密前后的数据
        System.out.println("加密前的数据：" + new String(plainText));
        System.out.println("加密后的数据：" + new String(encryptedKey, StandardCharsets.UTF_8));
        System.out.println("解密后的数据：" + new String(decryptedKey));
    }

    private static AsymmetricCipherKeyPair generateKeyPair() {
        SecureRandom random = new SecureRandom();

        // 生成质数p，长度为2048位
        BigInteger p = BigInteger.probablePrime(2048, random);

        // 设置模p的本原元g为2
        BigInteger g = BigInteger.valueOf(2);

        ElGamalParameters elGamalParameters = new ElGamalParameters(p, g);

        // 生成ElGamal密钥对
        ElGamalKeyPairGenerator keyPairGenerator = new ElGamalKeyPairGenerator();
        keyPairGenerator.init(new ElGamalKeyGenerationParameters(random, elGamalParameters));

        AsymmetricCipherKeyPair keyPair = keyPairGenerator.generateKeyPair();

        return keyPair;
    }

    private static SecretKey generateAesKey() {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            keyGenerator.init(128); // 使用128位的AES密钥
            return keyGenerator.generateKey();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}